package com.dailyblue.java.spring.boot.shopping.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dailyblue.java.spring.boot.commons.bean.JsonResult;
import com.dailyblue.java.spring.boot.commons.bean.ResultTool;
import com.dailyblue.java.spring.boot.shopping.bean.Goods;
import com.dailyblue.java.spring.boot.shopping.mapper.GoodsMapper;
import com.dailyblue.java.spring.boot.shopping.service.GoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class GoodsHashServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private GoodsMapper goodsMapper;

    private ListOperations<String, String> keys;
    private ValueOperations<String, String> value;
    // 所有商品在redis中的key
    private static final String LIST_KEY = "GOODS_ALL";
    // 我的购物车在redis中的key
    private static final String SHOPPING_LIST_KEY = "SHOPPING_CART";

    @Override
    public JsonResult findAll() {
        log.info("开始获取所有商品信息-------------------------------->");
        // 给hash和value赋值
        init();
        // 查询所有商品，现在redis中寻找，如果redis有，拿redis，如果没有，查询数据库并存放到redis
        List<String> list = keys.range(LIST_KEY, 0, -1);
        log.info("检查是否存在所有商品信息：{}", list);
        List<Goods> goods;
        if (list == null || list.size() == 0) {
            log.info("没有商品信息，查询数据库");
            // 没有，就需要把数据库的内容取出然后存放到redis中
            goods = goodsMapper.findAllGoods();
            for (int i = 0; i < goods.size(); i++) {
                log.info("开始将{}存放到redis中", goods.get(i));
                setRedis(goods.get(i), value, keys);
            }
            return ResultTool.success(goods);
        }
        goods = new ArrayList<>();
        log.info("redis中存在商品信息，获取每个商品");
        // 从redis中获取所有商品信息
        for (String key : list) {
            String goods_json = value.get(key);
            Goods good = JSONArray.parseObject(goods_json, Goods.class);
            goods.add(good);
            log.info("获取到{}的商品是{}", goods_json, good);
        }

        log.info("<--------------------------------结束获取所有商品信息");
        return ResultTool.success(goods);
    }

    @Override
    public JsonResult findById(int id) {
        init();

        return null;
    }

    @Override
    public JsonResult findAllGwc() {
        init();
        List<String> gwcList = keys.range(SHOPPING_LIST_KEY, 0, -1);
        if (gwcList == null || gwcList.size() == 0) {
            return ResultTool.fail(501, "购物车中没有商品！");
        }
        List<Goods> goods = new ArrayList<>();
        for (String s : gwcList) {
            String goods_json = value.get(s);
            Goods g = JSONArray.parseObject(goods_json, Goods.class);
            goods.add(g);
        }
        return ResultTool.success(goods);
    }

    @Override
    public JsonResult deleteById(int id) {
        init();
        keys.remove(SHOPPING_LIST_KEY, 1, "GOODS_ID:" + id);
        return findAllGwc();
    }

    @Override
    public JsonResult updateCartNum(int id, int num) {
        init();
        final String key = "GOODS_ID:" + id;
        // 1. 获取到id对应的商品信息
        String goods_json = value.get(key);
        Goods goods = JSONArray.parseObject(goods_json, Goods.class);
        // 2. 判断库存是否充足
        int stockNum = goods.getNum();
        if (stockNum == 0 && num == 1) {
            return ResultTool.fail(500, goods.getName() + "库存不足");
        }
        // 3. 如果是-1商品，刚好商品为0时 从购物车中剔除商品
        int gwcNum = goods.getGwcNum();
        if (gwcNum == 1 && num == -1) {
            return deleteById(id);
        }
        // 4. 开始更新购物车信息
        goods.setGwcNum(goods.getGwcNum() + num);
        // 5. 开始更新库存信息
        goods.setNum(goods.getNum() - num);
        value.set(key, JSONArray.toJSONString(goods));
        return findAllGwc();
    }

    @Override
    public JsonResult add(int id) {
        log.info("开始添加购物车信息-------------------------------->");
        // 1. 获取到id对应的商品信息
        String goods_json = value.get("GOODS_ID:" + id);
        Goods goods = JSONArray.parseObject(goods_json, Goods.class);
        log.info("获取到了{}对应的商品是:{}", id, goods);
        // 2. 判断库存是否充足
        int stockNum = goods.getNum();
        if (stockNum == 0) {
            log.info("库存不足");
            return ResultTool.fail(500, goods.getName() + "库存不足");
        }
        // 3. 将商品加入到购物车中
        List<String> gwcList = keys.range(SHOPPING_LIST_KEY, 0, -1);
        log.info("购物车中的商品信息是:{}", gwcList);
        // 3.1 判断这个商品在购物车中是否存在
        int index = gwcList.indexOf("GOODS_ID:" + id);
        log.info("{}商品在购物车中的位置是:{}", id, index);
        if (index == -1) {
            // 3.3 如果不存在 把商品存放到购物车中
            keys.rightPush(SHOPPING_LIST_KEY, "GOODS_ID:" + id);
            log.info("将{}存放到了SHOPPING_LIST_KEY", goods);
        } else {
            // 3.2 如果存在 更新购物车中的数量
            goods.setGwcNum(goods.getGwcNum() + 1);
            log.info("商品数量目前是:{}", goods.getGwcNum());
            String goods_json_update = JSONArray.toJSONString(goods);
            log.info("商品字符串是:{}", goods_json_update);
            value.getAndDelete("GOODS_ID:" + id);
            value.set("GOODS_ID:" + id, goods_json_update);
            log.info("GOODS_ID:{}在集合中已经存在，更新数量就行,新数量是:{}", id, goods.getGwcNum());
        }
        // 4. 更新商品的库存量
        goods.setNum(stockNum - 1);
        value.set("GOODS_ID:" + id, JSONArray.toJSONString(goods));
        log.info("更新商品库存数量:{}", goods.getNum());
        log.info("<--------------------------------结束添加购物车信息");
        return findAll();
    }

    @Override
    public JsonResult add2(int id) {
        return null;
    }

    private void init() {
        if (value == null) {
            value = stringRedisTemplate.opsForValue();
        }
        if (keys == null) {
            keys = stringRedisTemplate.opsForList();
        }
    }

    private void setRedis(Goods goods, ValueOperations<String, String> value, ListOperations<String, String> list) {
        // 将单个商品存放到redis中
        String key = "GOODS_ID:" + goods.getId();
        value.set(key, JSONArray.toJSONString(goods));
        // 将这个商品在记录到集合中
        list.rightPush(LIST_KEY, key);
        log.info("将{}存放到了value中并存放到了list李", key);
    }
}
